home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgramD2.iso / Borland / Borland C++ V5.02 / GDIDEMO.PAK / LINE.CPP < prev    next >
C/C++ Source or Header  |  1997-05-06  |  6KB  |  192 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows
  3. // Copyright (c) 1991, 1995 by Borland International, All Rights Reserved
  4. //
  5. //   MoveToLineTo demo window
  6. //----------------------------------------------------------------------------
  7. #include <owl/pch.h>
  8. #include <owl/dc.h>
  9. #include "line.h"
  10. #include <math.h>
  11.  
  12. //
  13. //
  14. //
  15. DEFINE_RESPONSE_TABLE1(TMoveToLineToWindow, TBaseDemoWindow)
  16.   EV_WM_SIZE,
  17. END_RESPONSE_TABLE;
  18.  
  19. IMPLEMENT_CASTABLE1(TMoveToLineToWindow, TBaseDemoWindow);
  20.  
  21. //
  22. //
  23. //
  24. TMoveToLineToWindow::TMoveToLineToWindow() : TBaseDemoWindow()
  25. {
  26.   Rotation = 0;
  27.   PointCount = MaxPoints;
  28.   Iconized = false;
  29.   RotatePoints();
  30. }
  31.  
  32. //
  33. //
  34. //
  35. void
  36. TMoveToLineToWindow::EvSize(uint sizeType, TSize& size)
  37. {
  38.   TBaseDemoWindow::EvSize(sizeType, size);
  39.   Invalidate();
  40.  
  41.   if (sizeType == SIZE_MINIMIZED) {
  42.     if (!Iconized) {
  43.       Rotation = 0;
  44.       Iconized = true;
  45.       PointCount = IconicPoints;
  46.       RotatePoints();
  47.     }
  48.   }
  49.   else {
  50.     if (Iconized) {
  51.       Rotation = 0;
  52.       Iconized = false;
  53.       PointCount = MaxPoints;
  54.       RotatePoints();
  55.     }
  56.   }
  57. }
  58.  
  59. //
  60. //
  61. //
  62. void
  63. TMoveToLineToWindow::TimerTick()
  64. {
  65.   RotatePoints();
  66.   if (Iconized) {
  67.     // Iconized windows don't process paint messages, so we'll manually
  68.     // update the image here.  Doing this painting during the timer tick
  69.     // will slow things down a bit, especially with several of these
  70.     // windows iconized at the same time.
  71.     //
  72.     Paint(TClientDC(*Parent), false, TRect());
  73.   }
  74.   else {
  75.     // In terms of Windows resources and system wide performance, letting
  76.     // paint do the work is 'faster' because it reduces the CPU time spent
  77.     // handling each timer tick.  Paint messages are low priority, so other
  78.     // messages like mouse clicks and other user input get processed first.
  79.     // The downside is that the paint messages are handled last, when
  80.     // there's nothing else to do, which can make animation look a bit jerky
  81.     // on a busy machine.
  82.     //
  83.     Invalidate(false);    // Let the Paint method draw the new figure...
  84.   }
  85. }
  86.  
  87. //
  88. //
  89. //
  90. void
  91. TMoveToLineToWindow::RotatePoints()
  92. {
  93.   // NOTE: all figures are in radians
  94.   const float M_2PI = 2 * M_PI;           // 2 pi radians in a circle
  95.   float StepAngle = M_2PI / PointCount;   // angular distance between points
  96.  
  97.   Rotation += M_PI / 32;   // Increment the angle of rotation of figure
  98.   if (Rotation > StepAngle)
  99.     Rotation -= StepAngle;   // Keep rotation less than distance between points
  100.  
  101.   // The loop below has i walking through the Points array, while j walks
  102.   // simultaneously through the angles to each point on the circle.  
  103.   // Incrementing j by StepAngle moves j to the next point on the circle with
  104.   // no complicated arithmetic (everything has been set up in advance of the
  105.   // loop).  Initializing j with Rotation causes the entire figure to shift
  106.   // clockwise a small amount.
  107.   //
  108.   int i;
  109.   float j;
  110.   for (i = 0, j = Rotation; i < PointCount; i++, j += StepAngle) {
  111.     Points[i].X = cos(j);   // These values will be multiplied by the
  112.     Points[i].Y = sin(j);   // current radius at display time.
  113.   }
  114. }
  115.  
  116. //
  117. //
  118. //
  119. void
  120. TMoveToLineToWindow::Paint(TDC& dc, bool, TRect&)
  121. {
  122.   TRect rect;
  123.   if (Iconized)
  124.     Parent->GetClientRect(rect);
  125.   else
  126.     GetClientRect(rect);
  127.  
  128.   int centerX = rect.right / 2;
  129.   int centerY = rect.bottom / 2;
  130.   int radius = min(centerY, centerX);
  131.  
  132.   // The follow memory DC operations are not required to draw lines, but
  133.   // were added to reduce screen flicker and speed up screen updates.
  134.   //
  135.   TMemoryDC  memDC(dc);
  136.  
  137.   TBitmap bitmap(dc, radius*2, radius*2);
  138.   memDC.SelectObject(bitmap);
  139.  
  140.   // Initiallize the new bitmap to all white.
  141.   //
  142.   memDC.PatBlt(0, 0, radius*2, radius*2, WHITENESS);
  143.  
  144.   // The Ellipse and the loop are all that's really needed to draw.  If you
  145.   // substitute dc for memDC, the draws will go directly to the screen.
  146.   // (Though the figure would no longer be centered, since the figure is drawn
  147.   // on a memDC bitmap, and the bitmap is then centered on the dc...)
  148.   // Since this line window is animated, it is frequently updated, which would
  149.   // cause the window to spend most of its time flickering if the dc were
  150.   // used.  Thus, the need for memory DC operations.  If the window were not
  151.   // animated, drawing onto the dc would look just fine.
  152.   //
  153.   memDC.Ellipse(0, 0, radius*2, radius*2);
  154.   int i,j;
  155.   for (i = 0; i < PointCount; i++) {
  156.     for (j = i + 1; j < PointCount; j++) {
  157.       memDC.MoveTo(radius + floor(Points[i].X * radius),
  158.                    radius + floor(Points[i].Y * radius));
  159.       memDC.LineTo(radius + floor(Points[j].X * radius),
  160.                    radius + floor(Points[j].Y * radius));
  161.     }
  162.   }
  163.  
  164.   // Now transfer what was drawn on the (invisible) memory DC onto the visible
  165.   // dc.  This one BitBlt transfer is much faster than the many 
  166.   // individual operations that were performed above.
  167.   //
  168.   dc.BitBlt(centerX-radius, centerY-radius, radius*2, radius*2, 
  169.             memDC, 0, 0, SRCCOPY);
  170.  
  171.   // Restore original bitmap before leaving
  172.   //
  173.   memDC.RestoreBitmap();
  174.                
  175.   // Footnotes:  Drawing this figure doesn't require a memory DC.  Animating
  176.   // the figure requires a memory DC only to reduce flicker to a tolerable 
  177.   // level.
  178.   // To make the animation faster still, (but use more memory, too),
  179.   // you could keep that memory DC hanging around between screen paints -
  180.   // constructing a DC takes some effort, and we're constructing one every 
  181.   // time we get a timer message.   You'd get the biggest improvement in 
  182.   // animation speed by calculating a sequence of bitmaps, then just 
  183.   // displaying them in the proper sequence.  This demo reconstructs the
  184.   // points list and redraws the figure for every timer message - a lot of
  185.   // work for the CPU, but it's code is simpler and doesn't use as much
  186.   // memory as more elaborate schemes might.
  187.  
  188.   // A challenge:  Turn the rotating figure into a ball that bounces off the
  189.   // walls of the window.  Don't forget the english (spin) the ball should 
  190.   // pick up when bouncing off the wall...
  191. }
  192.